import numpy as np
#* OpenCV库，用于图像处理
import cv2
#* 来自Python的abc模块，用于创建抽象基类
from abc import ABC, abstractmethod
'''
    input:接收要处理的图像(通常是numpy数组形式)
        (C,H,W)-彩色图像
    output:返回处理后的图像
        (C,H,W)-彩色图像
'''

# 实现部分抽象 - 滤镜接口
class ImageFilter(ABC):
    @abstractmethod
    def apply_filter(self, image):
        pass

# 具体滤镜实现
class CutoutFilter(ImageFilter):
    def apply_filter(self, image):
        # 简化版的木刻效果 - 使用颜色量化
        Z = image.reshape((-1,3))
        Z = np.float32(Z)
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
        K = 8
        _, label, center = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
        center = np.uint8(center)
        res = center[label.flatten()]
        return res.reshape((image.shape))

class BlurFilter(ImageFilter):
    def apply_filter(self, image):
        return cv2.GaussianBlur(image, (15, 15), 0)

class SharpenFilter(ImageFilter):
    def apply_filter(self, image):
        kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
        return cv2.filter2D(image, -1, kernel)

class TextureFilter(ImageFilter):
    def apply_filter(self, image):
        # 添加纹理效果
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        texture = cv2.imread('texture.jpg', 0) if cv2.imread('texture.jpg', 0) is not None else gray
        texture = cv2.resize(texture, (image.shape[1], image.shape[0]))
        return cv2.addWeighted(image, 0.7, cv2.cvtColor(texture, cv2.COLOR_GRAY2BGR), 0.3, 0)

# class CannyFilter(ImageFilter):
#     def apply_filter(self, image):
#         edges = cv2.Canny(image, 100, 200)
#         return cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)

class CannyFilter(ImageFilter):
    def __init__(self, blur_ksize=5, threshold1=50, threshold2=150, edge_thickness=1):
        """
        参数说明:
        :param blur_ksize: 高斯模糊核大小(奇数)
        :param threshold1: 第一个阈值(低阈值)
        :param threshold2: 第二个阈值(高阈值)
        :param edge_thickness: 边缘线粗细(1为原始效果)
        """
        self.blur_ksize = blur_ksize
        self.threshold1 = threshold1
        self.threshold2 = threshold2
        self.edge_thickness = edge_thickness
    
    def apply_filter(self, image):
        # 转换为灰度图
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        
        # 高斯模糊降噪
        blurred = cv2.GaussianBlur(gray, (self.blur_ksize, self.blur_ksize), 0)
        
        # Canny边缘检测
        edges = cv2.Canny(blurred, self.threshold1, self.threshold2)
        
        # 边缘加粗处理
        if self.edge_thickness > 1:
            kernel = np.ones((self.edge_thickness, self.edge_thickness), np.uint8)
            edges = cv2.dilate(edges, kernel)
        
        # 转换为彩色边缘图(白色边缘，黑色背景)
        edges_colored = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
        
        # 可选：将边缘叠加到原图上(红色边缘)
        # result = image.copy()
        # result[edges != 0] = (0, 0, 255)  # 将边缘设为红色
        
        return edges_colored